/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "iot_profile.h"
#include "iot_main.h"
#include "cJSON.h"
#include "iot_cloud.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* g_doorBellStatusMap[] ={"NO_PERSON_APPROACH","CALLING_BELL","UNKNOWN_PERSON_APPROACH"};
const char* g_driverStatusMap[] ={"ON","OFF"};

/**
 * @brief we make the data to a json string and send it to the iot cloud engine
 *
 */
int IotProfile_Report(int doorBellStatus,int lockStatus,int beep)
{
    int ret = -1;
    char *jsonString;
    IotProfileService service;
    IotProfileKV kvBeep;
    IotProfileKV kvLockStatus;
    IotProfileKV kvDoorBellStatus;

    /* package the data */
    service.eventTime = NULL;
    service.serviceID = "DoorBell";
    service.propertyLst = &kvDoorBellStatus;
    service.nxt = NULL;

    kvDoorBellStatus.key = "DoorBellStatus";
    kvDoorBellStatus.value = g_doorBellStatusMap[doorBellStatus];
    kvDoorBellStatus.type = IOT_PROFILE_KEY_DATATYPE_STRING;
    kvDoorBellStatus.nxt = &kvBeep;

    kvBeep.key = "Beep";
    kvBeep.value = beep ? "OFF":"ON";
    kvBeep.type = IOT_PROFILE_KEY_DATATYPE_STRING;
    kvBeep.nxt = &kvLockStatus;

    kvLockStatus.key = "LockStatus";
    kvLockStatus.value = lockStatus ? "OFF":"ON";
    kvLockStatus.type = IOT_PROFILE_KEY_DATATYPE_STRING;
    kvLockStatus.nxt = NULL;
    
    jsonString = IoTProfilePackage(&service);
    if (NULL != jsonString) {
        RaiseLog(LOG_LEVEL_INFO, "IotProfile_Report:[%s]", jsonString);
        ret = CLOUD_ReportMsg(jsonString);
        free(jsonString);
    } else {
        RaiseLog(LOG_LEVEL_ERR, "format the report message error");
    }
    return ret;
}

static int GetCommandSetBeep(CommandParamSetBeep *setBeepParam, cJSON *objCmd)
{
    cJSON *objPara = NULL;

    if (setBeepParam == NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }

    memset(setBeepParam, 0x00, sizeof(CommandParamSetBeep));
    if ((objPara = cJSON_GetObjectItem(objCmd, "Beep")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "cJSON_GetObjectItem Beep failed!\n");
        return -1;
    }
    if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
        setBeepParam->status = CN_BOARD_SWITCH_ON;
    } else {
        setBeepParam->status = CN_BOARD_SWITCH_OFF;
    }
    return 0;
}

static int GetCommandSetLock(CommandParamSetLock *setLockParam, cJSON *objCmd)
{
    cJSON *objPara = NULL;

    if (setLockParam == NULL || objCmd == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "NULL POINT!\n");
        return -1;
    }

    memset(setLockParam, 0x00, sizeof(CommandParamSetLock));
    if ((objPara = cJSON_GetObjectItem(objCmd, "Lock")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "cJSON_GetObjectItem Lock failed!\n");
        return -1;
    }

    if (0 == strcmp(cJSON_GetStringValue(objPara), "ON")) {
        setLockParam->status = CN_BOARD_SWITCH_ON;
    } else {
        setLockParam->status = CN_BOARD_SWITCH_OFF;
    }
    return 0;
}

/**
 * @brief deal the message received from the queue
 *
 */
static int DealSetBeepStatus(cJSON *objCmd)
{
    int ret = -1;
    cJSON *objParas = NULL;
    cJSON *objPara = NULL;
    CommandParamSetBeep setBeepParam;

    if ((objParas = cJSON_GetObjectItem(objCmd, "paras")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return ret;
    }

    if (GetCommandSetBeep(&setBeepParam, objParas) < 0) {
        RaiseLog(LOG_LEVEL_ERR, "GetCommandSetBeep failed!\n");
    }

    ret = IotProfile_CommandCallback(CLOUD_COMMAND_SET_BEEP, &setBeepParam);

    return ret;
}

static int DealSetLock(cJSON *objCmd)
{
    int ret = -1;
    cJSON *objParas = NULL;
    cJSON *objPara = NULL;
    CommandParamSetLock setLockParam;

    if ((objParas = cJSON_GetObjectItem(objCmd, "paras")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "Could not get paras in json");
        return ret;
    }

    if (GetCommandSetLock(&setLockParam, objParas) < 0) {
        RaiseLog(LOG_LEVEL_ERR, "GetCommandSetLock failed!\n");
    }

    ret = IotProfile_CommandCallback(CLOUD_COMMAND_SET_LOCK, &setLockParam);

    return ret;
}

int CLOUD_CommandCallBack(const char *jsonString)
{
    cJSON *objRoot = NULL;
    cJSON *objCmdName = NULL;
    int ret = -1;
    if (jsonString == NULL) {
        return ret;
    }

    if ((objRoot = cJSON_Parse(jsonString)) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "could not parse the payload\r\n");
        goto EXIT_JSONPARSE;
    }

    if ((objCmdName = cJSON_GetObjectItem(objRoot, "command_name")) == NULL) {
        RaiseLog(LOG_LEVEL_ERR, "%s:could not get the cmd name from json\r\n");
        goto EXIT_CMDOBJ;
    }

    if (0 == strcmp(cJSON_GetStringValue(objCmdName), "SetBeepStatus")) {
        ret = DealSetBeepStatus(objRoot);
    } else if (0 == strcmp(cJSON_GetStringValue(objCmdName), "SetLock")) {
        ret = DealSetLock(objRoot);
    } else {
        RaiseLog(LOG_LEVEL_ERR, "unresolved command:%d\r\n", cJSON_GetStringValue(objCmdName));
    }

EXIT_CMDOBJ:
EXIT_JSONPARSE:
    if (objRoot != NULL) {
        cJSON_Delete(objRoot);
    }
    return ret;
}